
#ifndef MINIMIZERSTATECOLLECTOR_H

#include <gsl_ext_cpp/GSLFunctionWrapper.h>
#include <gsl_ext_cpp/GSLMinimizerWrapper.h>
#include <gsl_ext_cpp/StoppingCriterion.h>

#include <octave/oct.h>

/// Implements methods for retrieving iteration states from GSL/GSL++ minimizers.
/**
 * The purpose of this class is to implement methods for 
 * retrieving the state of a minimization algorithm and storing 
 * this information to a GNU Octave struct.
 */
class MinimizerStateCollector
{
public:
  /// Constructs a new state collector for an n-dimensional minimizer.
  MinimizerStateCollector(int n);
  
  /// Frees the memory associated with this state collector.
  ~MinimizerStateCollector();
  
  /// Retrieves basic information from the state of a given minimizer.
  /**
   * This method retrieves the following information from the minimizer state:
   * - the current iterate \f$\mathbf{x}_{k}\f$
   * - the current gradient \f$\nabla f(\mathbf{x}_{k})\f$
   * - the current Hessian \f$\mathbf{H}_{f}(\mathbf{x}_{k})\f$
   * - the value that is tested against the given stopping criterion
   * @param[in] s the minimizer to retrieve the state information from
   * @param[in] f the function which to use for computing function, gradient and Hessian values
   * @param[in] stopCrit the user-supplied stopping criterion
   * @param[out] result the results stored in a GNU Octave struct
   */
  void collectStateData(const GSLMinimizerWrapper &s,
                        const GSLFunctionWrapper_fd2f &f,
                        const StoppingCriterion &stopCrit,
                        Octave_map &result);
protected:
  gsl_vector *g_;
  gsl_matrix *H_;
  
  virtual void collectAlgorithmSpecificData_(const GSLMinimizerWrapper &s,
                                             Octave_map &result) const { }
private:
  MinimizerStateCollector(const MinimizerStateCollector &msc);
  const MinimizerStateCollector &operator=(const MinimizerStateCollector &msc);
};

/// Retrieves the state of a GSL++ BFGS algorithm.
/**
 * The supported algorithms are gsl_ext_bfgs_hess_f, 
 * gsl_ext_bfgs_hess_mt, gsl_ext_bfgs_f and gsl_ext_bfgs_mt.
 */
class BFGSStateCollector : public MinimizerStateCollector
{
public:
  BFGSStateCollector(const string algorithmName, int n);
protected:
  void collectAlgorithmSpecificData_(const GSLMinimizerWrapper &s, Octave_map &resultMap) const;
private:
  const string ALGORITHM_NAME_;
};

/// Retrieves the state of a GSL++ conjugate gradient algorithm.
/**
 * The supported algorithms are gslpp_conjgrad_fr_mt and 
 * gslpp_conjgrad_pr_mt.
 */
class ConjGradStateCollector : public MinimizerStateCollector
{
public:
  ConjGradStateCollector(int n);
protected:
  void collectAlgorithmSpecificData_(const GSLMinimizerWrapper &s, Octave_map &resultMap) const;
};

/// Retrieves the state of a GSL++ simplex algorithm.
/**
 * This class supports the gslpp_lrwwsimplex algorithm.
 */
class SimplexStateCollector : public MinimizerStateCollector
{
public:
  SimplexStateCollector(int n);
protected:
  void collectAlgorithmSpecificData_(const GSLMinimizerWrapper &s, Octave_map &resultMap) const;
};

/// Implements methods for generating minimizer state collector instances.
class MinimizerStateCollectorFactory
{
public:
  /// Generates the appropriate state collector instance for the given algorithm.
  static MinimizerStateCollector *getInstance(const string &algorithmName, int n);
};

#define MINIMIZERSTATECOLLECTOR_H

#endif
